#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "universo.h"
#include "caixa.h"
#include "mercadoria.h"
#include "planeta.h"
#include "robo.h"
#include "linguagem.h"
#include "status.h"
#include "testes.h"
#include "nave.h"

#include "ator.h"

/** Vetor onde são armazenadas as mercadorias */
static TipoJogador listaJogadores[TOTAL_USUARIOS];

/** Variável que conta o número de usuários cadastrados */
static int numeroCadastrados = 0;

/** Vetor de strings com todos os servicos oferecidos */
static char *servicos_ConglomeradoAlegria[TOTAL_SERVICOS] = {"armazena","retira","verifica","cadastra","login","logout"};

/** Função que retorna um vetor de strings com todos os serviços oferecidos */
char** getServicos() {
   return servicos_ConglomeradoAlegria;
}

void programa() {
    teste();
   char listaComandos[1000],*auxiliar;
   int numeroComandos = 0;
   scanf("%s", listaComandos);
   registro("ConglomeradoAlegria",0);
   auxiliar = listaComandos;
   while(strchr(auxiliar,'-') != NULL) {
      auxiliar = strchr(auxiliar,'-');
      numeroComandos++;
      auxiliar++;
   }
   auxiliar = listaComandos;
   char strInstrucao[TAMANHO_INSTRUCAO],paramStr[TAMANHO_INSTRUCAO];
   int paramInt = 0,codInstrucao = 0,tamanhoComando = 0,i,j,k;
   for(i = 0;i < numeroComandos;i++) {
      for(j = 0;j < strlen(auxiliar) && auxiliar[j] != '-';j++)
         tamanhoComando++;
      j = 0;
      memset(strInstrucao,'\0',TAMANHO_INSTRUCAO);
      strncpy(strInstrucao,auxiliar,tamanhoComando);
      for(k = 0;k < TOTAL_INSTRUCOES && j == 0;k++) {
         if(strcmp(strInstrucao,getInstrucoes()[k]) == 0) {
            codInstrucao = k;
            j = 1;
         }
      }
      if(j == 0)
         codInstrucao = -1;
      tamanhoComando++;
      auxiliar += tamanhoComando;
      tamanhoComando = 0;
      for(j = 0;j < strlen(auxiliar) && auxiliar[j] != ';';j++)
         tamanhoComando++;
      memset(paramStr,'\0',TAMANHO_INSTRUCAO);
      strncpy(paramStr,auxiliar,tamanhoComando);
      j = 0;
      for(k = 0;k < getNumeroPlanetas() && j == 0;k++) {
         if(strcmp(paramStr,getNomePlanetas()[k]) == 0 || strcmp(paramStr,"0") == 0) {
            paramInt = k;
            j = 1;
         }
         if(k < getNumeroMercadorias() && j == 0 && strcmp(paramStr,getNomeMercadorias()[k]) == 0) {
            paramInt = k;
            j = 1;
         }
      }
      if(j == 0) {
         j = atoi(paramStr);
         if(j != 0)
            paramInt = j;
         else
            paramInt = -1;
      }
      if(tamanhoComando != strlen(auxiliar)) {
         tamanhoComando++;
         auxiliar += tamanhoComando;
      }
      tamanhoComando = 0;
      executaInstrucao(strInstrucao,codInstrucao,paramStr,paramInt);
   }
}

/** Função que inicializa o vetor para armazenar as mercadorias */
int inicializaArmazenamento() {
   int i,j;
   for(i = 0;i < TOTAL_USUARIOS;i++) {
      listaJogadores[i].statusLog = 0;
      for(j = 0;j < TOTAL_MAXIMO_MERCADORIAS;j++)
         listaJogadores[i].mercadoriasArmazenadas[j] = 0;
   }
   return STATUS_SUCESSO;
}

/** Função responsável por chamar as funções que realizarão os serviços oferecidos */
int ativaConglomeradoAlegria(char* strInstrucao,char *paramStr, int paramInt, int valor) {
   static int flag = 0;
   if(flag == 0)
      flag = inicializaArmazenamento();
   printf("\n\nRecebi a instrucao: %s-%s\n", strInstrucao,paramStr);
   if(verificaStatusLog(strInstrucao) == STATUS_SUCESSO) {
      switch(getStatusServico(strInstrucao)) {
         case instrArmazena: if(valor > 0)
                                armazenaMercadorias(paramInt);
                             else
                                printf("\nPagamento nao realizado.\n"); break;
         case instrRetira: retiraMercadorias(paramInt); break;
         case instrVerifica: verificaArmazenamento(paramStr); break;
         case instrCadastra: cadastraUsuario(paramStr); break;
         case instrLogin: login(paramStr); break;
         case instrLogout: logout(paramStr); break;
         default: printf("\nServico inexistente.\n\n"); break;
      }
   }
   else
      printf("\nNenhum usuario logado.\n\n");
   return STATUS_SUCESSO;
}

/** Função que verifica se um jogador está logado no sistema */
int verificaStatusLog(char *strInstrucao) {
   int i,status = STATUS_FALHA;
   if(strcmp(strInstrucao,"cadastra") == 0 || strcmp(strInstrucao,"login") == 0)
      status = STATUS_SUCESSO;
   for(i = 0;i < numeroCadastrados && status == STATUS_FALHA;i++)
      if(listaJogadores[i].statusLog == 1)
         status = STATUS_SUCESSO;
   return status;
}

/** Função responsável por cadastrar um novo usuário */
int cadastraUsuario(char *nome) {
   int status = getStatusCadastro(nome);
   if(status == STATUS_SUCESSO) {
      printf("\nDigite sua senha numerica: ");
      scanf("%d", &listaJogadores[numeroCadastrados].senha);
      strcpy(listaJogadores[numeroCadastrados].nome,nome);
      numeroCadastrados++;
      printf("\nCadastro realizado com sucesso.\n\n");
   }
   else
      printf("\nNao foi possivel realizar o cadastro. Usuario existente.\n");
   return status;
}

/** Função que verifica se é ou não possível cadastrar um novo usuário */
int getStatusCadastro(char *nome) {
   int i,status = STATUS_SUCESSO;
   for(i = 0;i < numeroCadastrados && status == STATUS_SUCESSO;i++)
      if(strcmp(listaJogadores[i].nome,nome) == 0)
         status = STATUS_FALHA;
   return status;
}

/** Função responsável por efetuar o login de um usuário no sistema */
int login(char *nome) {
   int status = getStatusLogin(nome);
   if(status != -1) {
      int senha;
      printf("\nDigite sua senha: ");
      scanf("%d", &senha);
      if(senha == listaJogadores[status].senha) {
         listaJogadores[status].statusLog = 1;
         printf("\n%s, voce esta logado.\n\n", listaJogadores[getUsuarioLogado()].nome);
      }
      else
         printf("\nSenha incorreta.\n");
   }
   else
      printf("\nNao foi possivel efetuar o login. Usuario inexistente ou algum usuario ja esta logado.\n\n");
   return status;
}

/** Função que verifica se um jogador pode ou não se logar no sistema */
int getStatusLogin(char *nome) {
   int i,status = -1;
   for(i = 0;i < numeroCadastrados && status == -1;i++)
      if(strcmp(listaJogadores[i].nome,nome) == 0)
         status = i;
   for(i = 0;i < numeroCadastrados;i++)
      if(listaJogadores[i].statusLog == 1)
         status = -1;
   return status;
}

/** Função responsável pelo logout de um usuário do sitema */
int logout(char *nome) {
   int i,j = -1,status = STATUS_FALHA;
   for(i = 0;i < numeroCadastrados && j == -1;i++)
      if(strcmp(listaJogadores[i].nome,nome) == 0)
         j = i;
   if(j == getUsuarioLogado()) {
      listaJogadores[j].statusLog = 0;
      printf("\nLogout realizado com sucesso.\n\n");
      status = STATUS_SUCESSO;
   }
   else
      printf("\nNao foi possivel realizar o logout do sistema.\n\n");
   return status;
}

/** Função que retorna o código do usuário logado */
int getUsuarioLogado() {
   int i,j = 0;
   for(i = 0;i < numeroCadastrados && j == 0;i++)
      if(listaJogadores[i].statusLog == 1)
         j = 1;
   return (i - 1);
}

/** Função que verifica qual serviço foi solicitado. Caso o serviço exista, retorna o código desse serviço. Caso contrário, retorna o valor da constante TOTAL_SERVICOS */
int getStatusServico(char *servico) {
   int statusServico = TOTAL_SERVICOS,i;
   for(i = 0;i < TOTAL_SERVICOS && statusServico == TOTAL_SERVICOS;i++)
      if(strcmp(servico,getServicos()[i]) == 0)
         statusServico = i;
   return statusServico;
}

/** Função responsável por armazenar as mercadorias indicadas */
void armazenaMercadorias(int quantidade) {
   if(getStatusArmazenamento(quantidade) == STATUS_SUCESSO) {
      listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()] += quantidade;
      desocupaCelula(getMercadoriaIndicada(),quantidade);
      printf("\nUsuario: %s\n", listaJogadores[getUsuarioLogado()].nome);
      puts("\n#==================================#\n#             Armazena             #\n#   +------------+------------+    #\n#   | mercadoria | quantidade |    #\n#   +------------+------------+    #");
      printf("#   | %-10s | %5d      |    #\n", getNomeMercadoriaIndicada(),quantidade);
      puts("#   +------------+------------+    #\n#==================================#\n");
   }
   else
      printf("Nao foi possivel realizar o armazenamento.\n");
}

/** Função que verifica se é ou não possível armazenar a quantidade desejada da mercadoria indicada */
int getStatusArmazenamento(int quantidade) {
   int status = STATUS_FALHA;
   if(strcmp(getNomeMercadoriaIndicada(),"") != 0) {
      int i;
      for(i = 0;i < TOTAL_MAXIMO_MERCADORIAS && status == STATUS_FALHA;i++)
         if(getCelulas()[i].mercadoria == getMercadoriaIndicada() && getCelulas()[i].quantidade > 0 && quantidade <= getCelulas()[i].quantidade && quantidade > 0)
            status = STATUS_SUCESSO;
   }
   return status;
}

/** Função responsável pela retirada de mercadorias que já foram previamente armazenadas */
void retiraMercadorias(int quantidade) {
   if(getStatusRetirada(quantidade) == STATUS_SUCESSO) {
      listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()] -= quantidade;
      ocupaCelula(getMercadoriaIndicada(),quantidade);
      printf("\nUsuario: %s\n", listaJogadores[getUsuarioLogado()].nome);
      puts("\n#==================================#\n#              Retira              #\n#   +------------+------------+    #\n#   | mercadoria | quantidade |    #\n#   +------------+------------+    #");
      printf("#   | %-10s | %5d      |    #\n", getNomeMercadoriaIndicada(),quantidade);
      puts("#   +------------+------------+    #\n#==================================#\n");
   }
   else
      printf("Nao foi possivel realizar a retirada.\n");
}

/** Função que verifica se é ou não possível retirar a quantidade desejada da mercadoria indicada */
int getStatusRetirada(int quantidade) {
   int status = STATUS_FALHA;
   if(strcmp(getNomeMercadoriaIndicada(),"") != 0) {
      int i,j = 0;
      for(i = 0;i < TOTAL_MAXIMO_MERCADORIAS && j == 0;i++)
         if(getCelulas()[i].mercadoria == getMercadoriaIndicada()) {
            j = 1;
            if ((CAPACIDADE_INICIAL_NAVE - getCelulas()[i].quantidade) >= quantidade && listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()] > 0
                && quantidade <= listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()])
               status = STATUS_SUCESSO;
         }
      if(j == 0 && listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()] > 0 && quantidade <= listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[getMercadoriaIndicada()])
         status = STATUS_SUCESSO;
   }
   return status;
}

/** Função que verifica se há mercadorias armazenadas e em caso positivo as imprime na tela */
int verificaArmazenamento(char *paramStr) {
   int status = STATUS_FALHA;
   if(strcmp(paramStr,"armazenamento") == 0) {
      int i,j = 0;
      for(i = 0;i < TOTAL_MAXIMO_MERCADORIAS;i++) {
         if(listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[i] > 0) {
            if(j == 0) {
               printf("\nUsuario: %s\n", listaJogadores[getUsuarioLogado()].nome);
               puts("\n#==================================#\n#     Mercadorias armazenadas      #\n#   +------------+------------+    #\n#   | mercadoria | quantidade |    #\n#   +------------+------------+    #");
            }
            printf("#   | %-10s | %5d      |    #\n", getNomeMercadorias()[i],listaJogadores[getUsuarioLogado()].mercadoriasArmazenadas[i]);
            puts("#   +------------+------------+    #");
            j++;
         }
      }
      if(j > 0) {
         puts("#==================================#\n");
         status = STATUS_SUCESSO;
      }
      else
         printf("Nao ha mercadorias armazenadas.\n");
   }
   else
      printf("Servico inexistente.\n");
   return status;
}
